﻿/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is tyzoh.jp code.
 *
 * The Initial Developer of the Original Code is Kazutaka Kurihara.
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */
using System;
using System.Collections;
using System.Drawing;
using System.Xml;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using Qurihara.QBasic;
using Microsoft.Ink;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization.Formatters.Soap;
using System.IO;

//using CSharpFilters;

namespace Qurihara
{
	/// <summary>
	/// Slide の概要の説明です。
	/// </summary>
	public class Slide
	{
		//private static string noLinkImageFileName = System.IO.Directory.GetCurrentDirectory() + @"\resorces\noLink.png";
		private FigureElementList elementList, relatedArrowList;//,drawList;
		private FigureElementList [] drawList;
		private ArrayList eventList;
		private int currentPosition;
		private string name; // スライドの名前
		public string DefaultDirectory;
		private int groupDepth;

        //スライドに変更があるかないか。より上位から、セーブの必要があるかどうかを判断するためにつかう。
        //本クラス内では、dirtyにかかわらずSaveが呼ばれればセーブする。
		private  bool dirty;
        public bool Dirty
        {
            get { return dirty; }
        }
		private Size slideSize;
        public Size SlideSize
        {
            get { return slideSize; }
            set { slideSize = value;
                if (SlideSizeInvalidated != null) SlideSizeInvalidated(this, new EventArgs());
            }
        }
		private Control parentControl;

		private Ink ink;

		private Qurihara.InkView view;
		public Qurihara.InkView View
		{
			get{return view;}
		}

//		private ViewSnapList viewSnapList;
//		public ViewSnapList ViewSnapList
//		{
//			get{return viewSnapList;}
//		}
		private Hashtable viewSnapListTable;
		public Hashtable ViewSnapListTable
		{
			get{return viewSnapListTable;}
		}
		public enum EVENT
		{
			ERASE_OBJECT = 0,
			MOVE_OBJECT = 1,
			CREATE_RECTANGLE = 2,
			CREATE_ELLIPSE = 3,
			CREATE_TEXT = 4,
			CREATE_BITMAP = 5,
			CREATE_ARROW = 6,
			CREATE_INK = 7,
			CREATE_LINE = 8,
			RESIZE_OBJECT = 9,
			CREATE_EXTERNAL = 10,
			GROUP_START = 11,
			GROUP_END = 12,
			CREATE_RECTANGLE_AND_TEXT = 13,
			CREATE_ELLIPSE_AND_TEXT = 14,
			CREATE_ELEMENT_GROUP = 15,
			RELEASE_ELEMENT_GROUP = 16,
			CREATE_STROKE = 17,
			CREATE_RECOG_GROUP = 18,
			RECOG_RECOG_GROUP = 19,
			CREATE_SCRATCH = 20,
            CREATE_LINK_IMAGE = 21,
		}

        public event EventHandler SlideLoaded = null;
        public event EventHandler SlideSizeInvalidated = null;

		public Slide(Size size,Control parentCont)
		{
			elementList = new FigureElementList();
			eventList = new ArrayList();
			relatedArrowList = new FigureElementList();
			//drawList = new FigureElementList();
			drawList = new FigureElementList[6];
			drawList[0] = new FigureElementList();
			drawList[1] = new FigureElementList();
			drawList[2] = new FigureElementList();
			drawList[3] = new FigureElementList();
			drawList[4] = new FigureElementList();
			drawList[5] = new FigureElementList();

			groupDepth = 0;
			slideSize = new Size(size.Width,size.Height);
			parentControl = parentCont;

			// おそらくclearAllされるからいらない項目。
			currentPosition = 0;
			dirty = false;

			//ListChangedハンドラ
			elementList.ListChanged +=new EventHandler(elementList_ListChanged);
			// View
			view = new Qurihara.InkView(parentCont.ClientSize,StrokeElement.inkCollector,parentCont);
			//view.ScreenSize = new Size(view.ScreenSize.Width/2,view.ScreenSize.Height/2);
			FigureElement.View = view;
			view.ViewChanged += new EventHandler(view_ViewChanged);

			BackGroundViewDependentElementList = new FigureElementList();
			ForeGroundViewDependentElementList = new FigureElementList();
			OnScreenElementList = new FigureElementList();
			OnScreenGrid = new Grid2DArrayList(4,4);

			//ViewSnapList
			//viewSnapList = new ViewSnapList();
			viewSnapListTable = new Hashtable();
			InitViewSnapListTable();
		}
		
		public string Name
		{
			get{return name;}
			set{name = value;}
		}
		
		public FigureElementList ElementList
		{
			get
			{
				return elementList;
			}
			set
			{
				elementList = value;
			}
		}
		public FigureElementList BackGroundViewDependentElementList = null;
		public FigureElementList ForeGroundViewDependentElementList = null;
		public FigureElementList OnScreenElementList = null;
		public Grid2DArrayList OnScreenGrid = null;

		/*
		public void copyToDrawList()
		{// 表示用の要素リストを作る
			drawList.Clear();
			for(int i=0;i<elementList.Count;i++)
			{
				drawList.Add(elementList[i]);
			}
		}
		*/

		private void elementList_ListChanged(object sender, EventArgs e)
		{
			updateDrawList();
		}
		private void view_ViewChanged(object sender, EventArgs e)
		{
			updateDrawList();
			parentControl.Invalidate();
		}
/*
		private void updateDrawList()
		{// 表示用の要素リストを整列する。
			drawList.Clear();
			IEnumerator enume;
			FigureElement fe;

			for(int pri=5;pri>=0;pri--)
			{
				enume = elementList.GetEnumerator();
				while(enume.MoveNext())
				{
					fe = (FigureElement)enume.Current;
					if (fe.Priority == pri)
					{
						if (view.IsVisibleOnScreen(fe.BoundingBox))
						{
							drawList.Add(fe);
						}
					}

				}
			}
		}
*/
		private static FigureElementPriorityComparer priorityComparer = new FigureElementPriorityComparer();
		private void updateDrawList()
		{// 表示用の要素リストを整列する。

			for(int i=0;i<6;i++) drawList[i].Clear();
			OnScreenElementList.Clear();
			OnScreenGrid.Clear();
			IEnumerator enume;
			FigureElement fe;

			enume = elementList.GetEnumerator();
			while(enume.MoveNext())
			{
				fe = (FigureElement)enume.Current;
				if (view.IsVisibleOnScreen(fe.BoundingBox))
				{
					//drawList[fe.Priority].Add(fe);
					drawList[0].Add(fe);
					OnScreenElementList.Add(fe);
					OnScreenGrid.Add(DrawingUtil.GetRelativeRectangle(view.ViewRectangle,fe.BoundingBox),fe);
				}
			}
			drawList[0].Sort(priorityComparer);
		}
// 旧バージョン３ ６リスト制
//		private void updateDrawList()
//		{// 表示用の要素リストを整列する。
//
//			for(int i=0;i<6;i++) drawList[i].Clear();
//			OnScreenElementList.Clear();
//			OnScreenGrid.Clear();
//			IEnumerator enume;
//			FigureElement fe;
//
//			enume = elementList.GetEnumerator();
//			while(enume.MoveNext())
//			{
//				fe = (FigureElement)enume.Current;
//					if (view.IsVisibleOnScreen(fe.BoundingBox))
//					{
//						drawList[fe.Priority].Add(fe);
//						OnScreenElementList.Add(fe);
//						OnScreenGrid.Add(DrawingUtil.GetRelativeRectangle(view.ViewRectangle,fe.BoundingBox),fe);
//					}
//			}
//		}
		/*  旧バージョン２
 		public void updateDrawList()
		{// 表示用の要素リストを整列する。
			drawList.Set(elementList);
			if (drawList.Count > 1)
			{
				// まず矢印の描画順を後にする。
				FigureElementList tmpList = new FigureElementList();
				//drawList.AddSubListTypeOf(typeof(ArrowElement),ref tmpList);
				tmpList.AddSubListTypeOf(typeof(ArrowElement),drawList);
				drawList.Remove(tmpList);
				drawList.Add(tmpList);
				tmpList.Clear();
				// つぎに直線の描画順を後にする。
				//drawList.AddSubListTypeOf(typeof(LineElement),ref tmpList);
				tmpList.AddSubListTypeOf(typeof(LineElement),drawList);
				drawList.Remove(tmpList);
				drawList.Add(tmpList);
				tmpList.Clear();
				// つぎにテキストの描画順を後にする。
				//drawList.AddSubListTypeOf(typeof(TextElement),ref tmpList);
				tmpList.AddSubListTypeOf(typeof(TextElement),drawList);
				drawList.Remove(tmpList);
				drawList.Add(tmpList);
				tmpList.Clear();
			}
			
		}
*/
/*
		public void updateDrawList()
		{// 表示用の要素リストを整列する。
			bool ok;
			int i;
			drawList.Set(elementList);
			//copyToDrawList();
			if (drawList.Count > 1)
			{
				// 旧バージョン。包含関係を考えるものだが不完全。
				FigureElementList listBoxedBy = new FigureElementList();
				while(true)
				{
					// 先頭要素を包む要素を探す。
					drawList.getBoxingElementList((FigureElement)drawList[0],ref listBoxedBy);
					// 自分自身は除く
					listBoxedBy.Remove(drawList[0]);
					// もし包む要素があるならば
					if (listBoxedBy.Count == 0) break;
					// もし先頭と包む要素がまったく同じ大きさのものだけからなるときは終了。
					ok = false;
					for (i=0;i<listBoxedBy.Count;i++)
					{
						if (((FigureElement)drawList[0]).BoundingBox.Equals(((FigureElement)listBoxedBy[i]).BoundingBox) == false)
						{
							ok = true;
							break;
						}
					}
					if (!ok) break;
					// 自分はそいつらよりも後に描画されるべきだから、そいつらの一番後ろに追加する。
					drawList.Insert(drawList.IndexOf(listBoxedBy[listBoxedBy.Count-1])+1,drawList[0]);
					drawList.RemoveAt(0);
				}
				listBoxBy.Clear();
				
			}
			
		}
*/
        //drawingを導入した理由：inkCollector.Enable=falseにすると、その瞬間form.paintがよびだされておかしなことになり、かつmutexやlockでもはじけないため。
        private static bool drawing = false;

		public void draw(Graphics g,bool showNoEdittingElement)
		{
            if (!drawing)
            {
                drawing = true;
                //bool disabledFlag = false;
                //if (!View.InkCollector.CollectingInk && View.IsBusyMode)
                //{
                //    View.InkCollector.Enabled = false;
                //    disabledFlag = true;
                //}
                //座標変換
                view.GraphicsTransform(g);
                view.InkRendererTransform();

                // 表示する
                BackGroundViewDependentElementList.draw(g, showNoEdittingElement);
                //elementList.draw(g);
                //drawList.draw(g,showNoEdittingElement);
                for (int i = 5; i >= 0; i--) drawList[i].draw(g, showNoEdittingElement);
                ForeGroundViewDependentElementList.draw(g, showNoEdittingElement);

                view.InkRendererResume();
                view.GraphicsResume(g);
                //if (disabledFlag)
                //{
                //    View.InkCollector.Enabled = true;
                //}
                drawing = false;
            }
		}
		private void drawWithoutInk(Graphics g,bool showNoEdittingElement)
		{// SaveAsBitmap用
			//座標変換
			view.GraphicsTransform(g);

			//drawList.drawWithoutInk(g,showNoEdittingElement);
			for(int i=5;i>=0;i--) drawList[i].drawWithoutInk(g,showNoEdittingElement);
		}
		private bool stepForward()
		{
			if (currentPosition == eventList.Count) // これでcurrentPosition は最大でも添え字の最大値+1 ( a[5] なら5) にしかならない。
				return false;
			else
			{
				currentPosition++;
				return true;
			}
		}
		private bool stepBack()
		{
			if (currentPosition == 0)
				return false;
			else
			{
				currentPosition--;
				return true;
			}
		}
		public bool Do()
		{
			if (currentPosition == eventList.Count)
			{
				if (groupDepth >0) System.Diagnostics.Debug.Fail("slide file broken.");
				return false;
			}
			else
			{
				((IEvent)eventList[currentPosition]).Do();

				if (((IEvent)eventList[currentPosition]).Type == Slide.EVENT.GROUP_START)
				{
					groupDepth++;
				} 
				else
					if (((IEvent)eventList[currentPosition]).Type == Slide.EVENT.GROUP_END)
				{
					groupDepth--;
				} 
				stepForward();
				if (groupDepth > 0) Do();
				//updateDrawList();
				dirty = true;
				return true;
			}
		}
		public bool UnDo()
		{
			if (stepBack() == false)
			{
				if (groupDepth >0) System.Diagnostics.Debug.Fail("slide file broken.");
				return false;
			}
			else
			{
				((IEvent)eventList[currentPosition]).UnDo();
				if (((IEvent)eventList[currentPosition]).Type == Slide.EVENT.GROUP_END)
				{
					groupDepth++;
				} else
				if (((IEvent)eventList[currentPosition]).Type == Slide.EVENT.GROUP_START)
				{
					groupDepth--;
				} 
				if (groupDepth > 0) UnDo();
				//updateDrawList();
				dirty = true;
				return true;
			}
		}
		public void insertEvent(object ev) // これでappendもできる。
		{ 

			// UnDoのあとにinsertしたときは、巻き戻した履歴は消える。
			int endIndex = eventList.Count-1;
			if (endIndex >= currentPosition)
			{
				eventList.RemoveRange(currentPosition,endIndex-currentPosition+1);
			}
			eventList.Insert(currentPosition,ev);
			// タイムスタンプを書き込む。
			((IEvent)ev).TimeStamp = DateTime.Now.Ticks;

			// 消されたeventのメモリ開放をせよ。
		}
		public  void clearAll()
		{
			// ちゃんとメモリ開放してね。
			elementList.Clear();
			//drawList.Clear();
			for(int i=0;i<6;i++) drawList[i].Clear();
			OnScreenElementList.Clear();
			OnScreenGrid.Clear();
			BackGroundViewDependentElementList.Clear();
			ForeGroundViewDependentElementList.Clear();
			
			eventList.Clear();

			FigureElement.ResetPriorityCounter();

			currentPosition = 0;
			dirty = false;

			if (ink != null) ink = null;
			ink = new Ink();
			StrokeElement.ResetInk(ink);
			
			//StrokeElement.ResetInk(new Ink());
			view.ViewRectangle = new Rectangle(0,0,view.ScreenSize.Width,view.ScreenSize.Height);

			InitViewSnapListTable();

		}
		private void InitViewSnapListTable()
		{
			viewSnapListTable.Clear();
			ViewSnapList vs = new ViewSnapList("default");
			viewSnapListTable.Add(vs.Id,vs);
		}
		public bool isEmpty()
		{
			// 051115
			return false;
//			if (eventList.Count == 0)
//			{
//				return true;
//			}
//			else
//			{
//				return false;
//			}
		}
// 以下の関数がEventにも存在するのは無駄だろうか。
		protected FigureElement getElementFromID(int ID)
		{
			if (ID <0 || ID >= elementList.Count) return null;
			return (FigureElement)elementList[ID]; 
		}

// ***************** 以後は各イベントの生成。自動化も可能にする。
		private void __EraseObject(int ID)
		{ // Slide.Load()専用。内部用。単純に消すだけ。

			if (getElementFromID(ID) != null)
			{
				insertEvent(new EraseObjectEvent(elementList,ID));
				Do();
			}
		}
		private void _EraseObject(int ID)
		{ // 矢印の両端になっていないか確かめない。内部用。

			if (getElementFromID(ID) != null)
			{
				// ElementGroupの場合は内部を消去する。
				if (elementList[ID].GetType() == typeof(ElementGroupElement))
				{
					ElementGroupElement gl = (ElementGroupElement)elementList[ID];
					GroupStart();
					insertEvent(new EraseObjectEvent(elementList,ID));
					Do();
					insertEvent(new ReleaseElementGroupEvent(elementList,gl));
					this.EraseObjects(gl.groupElementList);
					Do();
					GroupEnd();
				}
				else
				{
					insertEvent(new EraseObjectEvent(elementList,ID));
					Do();
				}
				//updateDrawList();
			}
		}
		public void MoveObject(int ID,int addx,int addy)
		{
			insertEvent(new MoveObjectEvent(elementList,ID,addx,addy));
			Do();
			updateDrawList();//Create系と違ってelement_changedイベントが発生しないので自主的にやる。
		}
		public FigureElement createRectangle(int prio,Rectangle r,Color fc,Color oc,int ow)
		{
			ObjectEvent oe = new CreateRectangleEvent(elementList,parentControl,prio,r,fc,oc,ow);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createEllipse(int prio,Rectangle r,Color fc,Color oc,int ow)
		{
			ObjectEvent oe = new CreateEllipseEvent(elementList,parentControl,prio,r,fc,oc,ow);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createText(int prio,Rectangle r,string t,Color c,Font f)
		{
			ObjectEvent oe = new CreateTextEvent(elementList,parentControl,prio,r,t,c,f);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createBitmap(int prio,Rectangle r,string bitmapfile)
		{
			ObjectEvent oe = new CreateBitmapEvent(elementList,parentControl,prio,r,bitmapfile);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createBitmap(int prio,Rectangle r,Bitmap bm)
		{
			ObjectEvent oe = new CreateBitmapEvent(elementList,parentControl,prio,r,bm);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createScratch(int prio,Rectangle r,string bitmapfile)
		{
			ObjectEvent oe = new CreateScratchEvent(elementList,parentControl,prio,r,bitmapfile);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createScratch(int prio,Rectangle r,Bitmap bm)
		{
			ObjectEvent oe = new CreateScratchEvent(elementList,parentControl,prio,r,bm);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createArrow(int prio,int fID,int tID,Color c,System.Drawing.Drawing2D.DashStyle ds)
		{
			ObjectEvent oe = new CreateArrowEvent(elementList,parentControl,prio,fID,tID,c,ds);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createLine(int prio,Rectangle r,int sx,int sy,int ex,int ey,Color c,System.Drawing.Drawing2D.DashStyle ds)
		{
			ObjectEvent oe = new CreateLineEvent(elementList,parentControl,prio,r,sx,sy,ex,ey,c,ds);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public void ResizeObject(int ID,int addx,int addy,int addwidth,int addheight)
		{ // 相対変化値でやります。
			insertEvent(new ResizeObjectEvent(elementList,ID,addx,addy,addwidth,addheight));
			Do();
			updateDrawList();//Create系と違ってelement_changedイベントが発生しないので自主的にやる。
		}
		public FigureElement createExternal(int prio,Rectangle r,string file)
		{
			ObjectEvent oe = new CreateExternalEvent(elementList,parentControl,prio,r,file);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
        public FigureElement createLinkImage(int prio, Rectangle r, string file,string hash,int reflesh,bool persist)
        {
            ObjectEvent oe = new CreateLinkImageEvent(elementList, parentControl, prio, r, file,hash,reflesh,persist);
            insertEvent(oe);
            Do();
            return oe.figureElement;
        }
        public void GroupStart()
		{
			insertEvent(new GroupStartEvent());
			stepForward();
			//Do(); これをやるとFail
		}
		public void GroupEnd()
		{
			insertEvent(new GroupEndEvent());
			stepForward();
			//Do(); これをやるとFail
		}
		public FigureElement createElementGroup(int prio,ArrayList list)
		{
			ObjectEvent oe = new CreateElementGroupEvent(elementList,parentControl,prio,list);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public void ReleaseElementGroup(int ID)
		{
			insertEvent(new ReleaseElementGroupEvent(elementList,ID));
			Do();
		}
		public FigureElement createStroke(int prio,Rectangle r,int id)
		{
			ObjectEvent oe = new CreateStrokeEvent(elementList,parentControl,prio,r,id);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createObject(CreateObjectEvent coe)
		{// 一般形
			insertEvent(coe);
			Do();
			//updateDrawList();
			return coe.figureElement;
		}
		public FigureElement createRecogGroup(int prio,ArrayList list,ArrayList rlist)
		{
			ObjectEvent oe = new CreateRecogGroupEvent(elementList,parentControl,prio,list,rlist);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public void RecogObject(int ID)
		{
			insertEvent(new RecognizeRecogGroupEvent(elementList,ID));
			Do();
		}
		// *************   以後は特殊なイベント生成。自動化不可。
		public FigureElement createInk(int prio,Rectangle r,Bitmap bm)
		{ // 保存時にBitmapに置き換わります。
			ObjectEvent oe = new CreateInkEvent(elementList,parentControl,prio,r,bm); 
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}
		public FigureElement createInk(int prio,Rectangle r,Bitmap bm,bool isRehearsal)
		{ // 保存時にBitmapに置き換わります。
			ObjectEvent oe = new CreateInkEvent(elementList,parentControl,prio,r,bm,isRehearsal); 
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}


		public void EraseObject(int ID)
		{ // 矢印の両端になっていないか確かめる。外部用。
			if (ID >= 0 && ID < elementList.Count)
			{
				relatedArrowList.Clear();
				elementList.AddRelatedArrowList(ref relatedArrowList,getElementFromID(ID));
				_EraseObjects(relatedArrowList); // 内部用を呼び出して関連矢印を先に消す。
				_EraseObject(ID); // 内部用で自分を消す。
			}
		}

		private void _EraseObjects(FigureElementList fel)
		{ // 矢印の両端になっていないか確かめない。 内部用。
			IEnumerator enume = fel.GetEnumerator();
			while (enume.MoveNext())
			{
				_EraseObject(elementList.IndexOf((FigureElement)enume.Current));
			}
		}		
		public void EraseObjects(FigureElementList fel)
		{ // 矢印の両端になっていないか確かめる。外部用。
			GroupStart();
			IEnumerator enume = fel.GetEnumerator();
			while (enume.MoveNext())
			{
				// 矢印チェック付き消去を呼び出す。
				EraseObject(elementList.IndexOf((FigureElement)enume.Current));
			}
			GroupEnd();
		}
		public void EraseAllObjects()
		{ // 矢印の両端になっていないか確かめる。外部用。
			// all は、消去用のリスト。elementList本体だと、Enumeratorが作れない。
			GroupStart();
			FigureElementList all= new FigureElementList(); // メモリむだ。
			IEnumerator enume = elementList.GetEnumerator();
			while (enume.MoveNext())
			{
				all.Add((FigureElement)enume.Current);
			}
			
			// 矢印チェック付き消去。
			EraseObjects(all);
			/* 古いバージョン。
			for (int i=elementList.Count-1; i>=0; i--)
			{
				EraseObject(i);
			}
			*/
			GroupEnd();
		}
		public void MoveObject(FigureElement fe,int addx,int addy)
		{
			MoveObject(elementList.IndexOf(fe),addx,addy);
		}
		public void MoveObjects(FigureElementList fel,int addx,int addy)
		{
			GroupStart();
			IEnumerator enume = fel.GetEnumerator();
			while (enume.MoveNext())
			{
				MoveObject(elementList.IndexOf((FigureElement)enume.Current),addx,addy);
			}
			GroupEnd();
		}
		public void ResizeObjects(FigureElementList fel,int x,int y,int width,int height)
		{
			ArrayList incRectList = new ArrayList();
			Rectangle r = new Rectangle();
			fel.GetBoundingBox(ref r);
			fel.getLinearResizeIncrement(r,x,y,width,height,ref incRectList);
			GroupStart();
			for(int i=0;i<fel.Count;i++)
			{
				r = (Rectangle)incRectList[i];
				ResizeObject(elementList.IndexOf((FigureElement)fel[i])
					,r.X,r.Y,r.Width,r.Height);
			}
			GroupEnd();
			incRectList.Clear();
		}
		public void ResizeObject(FigureElement fe,int x,int y,int w,int h)
		{
			ResizeObject(elementList.IndexOf(fe),x,y,w,h);
		}

		public void CopyAndPasteObjects(ref FigureElementList felo,ref FigureElementList newObjectsList,int addx,int addy)
		{ // (addx,addy)ずれた場所にオブジェクトのコピーを作成する。
			if (felo.Count > 0)
			{
				FigureElementList fel = new FigureElementList();
				fel.Add(felo);

				FigureElement fe,ce,te;
				//FigureElementList newObjectsList = new FigureElementList();
				IEnumerator enume,enume2;
				QArrayList tmpList = new QArrayList();

				// GroupElementの前処理
				QArrayList tmpList2 = new QArrayList();
				enume = fel.GetEnumerator();
				while(enume.MoveNext())
				{
					fe =(FigureElement)enume.Current;
					if (fe is ElementGroupElement)
					{
						((ElementGroupElement)fe).GetAllGroupedElementList(ref tmpList);
						tmpList2.Add(fe);
					}
				}
				fel.Remove(tmpList2);//いったんElementGroupElementを消して
				fel.AddNewElement(tmpList);// GroupedElementListとしてすべて追加。

				// 矢印オブジェクトのための前処理
				// 矢印の端点オブジェクトがあるか確認し、なければ追加し、
				// 矢印自体はリストの後方に置きなおす。
				tmpList.Clear();
				enume = fel.GetEnumerator();
				while(enume.MoveNext())
				{
					fe =(FigureElement)enume.Current;
					if (fe.GetType() == typeof(ArrowElement))
					{
						te = ((ArrowElement)fe).fromElement;
						if (fel.IndexOf(te) == -1)
						{
							tmpList.Add(te);
						}
						te = ((ArrowElement)fe).towardElement;
						if (fel.IndexOf(te) == -1)
						{
							tmpList.Add(te);
						}
						tmpList.Add(fe);
					}
				}
				fel.Remove(tmpList);
				fel.Add(tmpList);
				
				// 複製開始。
				GroupStart();
				newObjectsList.Clear();
				int [] transferIndex = new int[elementList.Count];

				enume = fel.GetEnumerator();
				while (enume.MoveNext())
				{  // felには矢印もある。しかし矢印の生成は端点オブジェクトの生成より必ず後。
					fe =(FigureElement)enume.Current;
					fe.createCopy(out ce);

					if (ce is ElementGroupElement)
					{
						((ElementGroupElement)ce).groupElementList.Clear();


						enume2 = ((ElementGroupElement)fe).groupElementList.GetEnumerator();
						while(enume2.MoveNext())
						{
							((ElementGroupElement)ce).groupElementList.Add(
									getElementFromID(transferIndex[elementList.IndexOf(enume2.Current)])
								);
						}
					}
					if (ce.GetType() == typeof(ArrowElement))
					{
						//arrow
						ArrowElement ae = (ArrowElement)ce;
						ae.fromElement = getElementFromID(transferIndex[elementList.IndexOf(((ArrowElement)fe).fromElement)]);
						ae.towardElement = getElementFromID(transferIndex[elementList.IndexOf(((ArrowElement)fe).towardElement)]);
					}

					CreateObjectEvent coe;
					ce.createCreateEvent(elementList,out coe);
					insertEvent(coe);
				

					Do();
					//updateDrawList();
					newObjectsList.Add(ce);
					transferIndex[elementList.IndexOf(fe)]=elementList.IndexOf(ce);
				}

				// ずらす
				//MoveObjects(newObjectsList,addx,addy);
				MoveObjects(felo,addx,addy);

				GroupEnd();

				tmpList.Clear();
				tmpList2.Clear();
				fel.Clear();
			}
		}

		public void FormBySize(FigureElementList listToForm)
		{
			int meanWidth=0,meanHeight=0,num=0;
			IEnumerator enume;
			enume = listToForm.GetEnumerator();
			while (enume.MoveNext())
			{
				if (((FigureElement)enume.Current) is WakuElement)
				{
					meanWidth += ((FigureElement)enume.Current).BoundingBox.Width;
					meanHeight += ((FigureElement)enume.Current).BoundingBox.Height;
					num++;
				}
			}
			if (num > 0)
			{
				GroupStart();
				meanWidth /= num;
				meanHeight /= num;
				int modifyx,modifyy,modifyw,modifyh;
				Rectangle r;
				enume = listToForm.GetEnumerator();
				while (enume.MoveNext())
				{
					if (((FigureElement)enume.Current) is WakuElement)
					{
						r = ((FigureElement)enume.Current).BoundingBox;
						modifyw = meanWidth - r.Width;
						modifyh = meanHeight - r.Height;
						modifyx = -modifyw / 2;
						modifyy = -modifyh / 2;
						ResizeObject((FigureElement)enume.Current,modifyx,modifyy,modifyw,modifyh);
					}
				}
				GroupEnd();
			}

		}
		public void UnifyAxis(FigureElementList fel,bool isVertical)
		{
			int xx = 0;
			int num = 0;
			IEnumerator enume;
			enume = fel.GetEnumerator();
			while (enume.MoveNext())
			{
				if (((FigureElement)enume.Current).GetType() != typeof(ArrowElement))
				{
					num++;
					if (isVertical)
					{
						xx += ((FigureElement)enume.Current).MidPoint.X;
					}
					else
					{
						xx += ((FigureElement)enume.Current).MidPoint.Y;
					}
				}
			}
			if (num > 0)
			{
				GroupStart();
				xx = (int)(xx / num);

				enume = fel.GetEnumerator();
				while (enume.MoveNext())
				{
					if (((FigureElement)enume.Current).GetType() != typeof(ArrowElement))
					{
						if (isVertical)
						{
							MoveObject((FigureElement)enume.Current
								,xx - ((FigureElement)enume.Current).MidPoint.X
								,0);
						}
						else
						{
							MoveObject((FigureElement)enume.Current
								,0
								,xx - ((FigureElement)enume.Current).MidPoint.Y);
						}
					}
				}
				GroupEnd();
			}
		}
		public void AlignAxis(FigureElementList fel,bool isVertical)
		{
			Rectangle bounds = new Rectangle();
			FigureElementList sortList = new FigureElementList();

			IEnumerator enume;
			enume = fel.GetEnumerator();
			while(enume.MoveNext())
			{
				if (((FigureElement)enume.Current).GetType() != typeof(ArrowElement))
				{
					sortList.Add(enume.Current);
				}
			}
			sortList.Sort(new Qurihara.FigureElementMidPointComparer(!isVertical));

			if (sortList.Count > 1)
			{
				sortList.GetBoundingBox(ref bounds);
				int add=0;
				if (isVertical)
				{
					add = bounds.Height/sortList.Count;
				}
				else
				{
					add = bounds.Width/sortList.Count;
				}
				GroupStart();
				for(int ind=0;ind<sortList.Count;ind++)
				{
					if (isVertical)
					{
						MoveObject((FigureElement)sortList[ind]
							,0
							,ind*add+ bounds.Y - ((FigureElement)sortList[ind]).MidPoint.Y);
					}
					else
					{
						MoveObject((FigureElement)sortList[ind]
							,ind*add+ bounds.X - ((FigureElement)sortList[ind]).MidPoint.X
							,0);
					}
					
				}
				GroupEnd();
			}
			sortList.Clear();
		}


		public FigureElement createElementGroup(ref FigureElementList listToGroup)
		{   // 外部用。
			if (listToGroup.Count > 1)
			{
				IEnumerator enume;
				FigureElement fe,te1,te2;
				FigureElementList removeArrowList = new FigureElementList();
				// 矢印オブジェクトのための前処理
				// 矢印をグループに加える場合、
				// 矢印の両端が同時にグループ化されなければ
				// その矢印もグループ化しない。
				enume = listToGroup.GetEnumerator();
				while(enume.MoveNext())
				{
					fe =(FigureElement)enume.Current;
					if (fe.GetType() == typeof(ArrowElement))
					{
						te1 = ((ArrowElement)fe).fromElement;
						te2 = ((ArrowElement)fe).towardElement;
						if (listToGroup.IndexOf(te1) == -1 
							|| listToGroup.IndexOf(te2) == -1)
						{
							removeArrowList.Add(fe);
						}
					}
				}
				listToGroup.Remove(removeArrowList);
				removeArrowList.Clear();

				//イベント生成。
				ObjectEvent oe = new CreateElementGroupEvent(elementList,parentControl,-1,listToGroup); 
				insertEvent(oe);
				Do();
				//updateDrawList();
				return oe.figureElement;
			}
			return null;
		}
		public void ReleaseElementGroup(ref FigureElementList listToRelease)
		{   // 外部用。
			if (listToRelease.Count > 0)
			{
				GroupStart();
				IEnumerator enume;
				FigureElement fe;//,te1,te2;
				//FigureElementList removeArrowList = new FigureElementList();
				// リストに含まれるグループエレメントをすべて解除する。
				enume = listToRelease.GetEnumerator();
				while(enume.MoveNext())
				{
					fe =(FigureElement)enume.Current;
					if (fe.GetType() == typeof(ElementGroupElement))
					{
						insertEvent(new ReleaseElementGroupEvent(elementList,(ElementGroupElement)fe));
						Do();
					}
				}
				GroupEnd();
				//updateDrawList();
			}
		}

		public FigureElement createStroke(int prio,Rectangle r,Stroke s)
		{ // 外部用
			ObjectEvent oe= new CreateStrokeEvent(elementList,parentControl,prio,r,s);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}

		public void ChangeColor(FigureElementList fel,Color c)
		{ // 塗り色属性をもつ要素の色を変更するイベント
			FigureElement fe,ce;
			IEnumerator enume = fel.GetEnumerator();
			bool flag = false;
			while(enume.MoveNext())
			{
				if (enume.Current is IHasFillColor) 
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				GroupStart();
				enume = fel.GetEnumerator();
				while(enume.MoveNext())
				{
					if (enume.Current is IHasFillColor)
					{
						fe = (FigureElement)enume.Current;
						fe.createCopy(out ce);
						((IHasFillColor)ce).FillColor = c;
						ChangeObjectProperty(fe,ce);
					}
				}
				GroupEnd();
			}
		}
		public void ChangeOutLineColor(FigureElementList fel,Color c,int w)
		{ // 縁取り色属性をもつ要素の色と幅を変更するイベント
			FigureElement fe,ce;
			IEnumerator enume = fel.GetEnumerator();
			bool flag = false;
			while(enume.MoveNext())
			{
				if (enume.Current is IHasOutLineColor) 
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				GroupStart();
				enume = fel.GetEnumerator();
				while(enume.MoveNext())
				{
					if (enume.Current is IHasOutLineColor)
					{
						fe = (FigureElement)enume.Current;
						fe.createCopy(out ce);
						((IHasOutLineColor)ce).OutLineColor = c;
						((IHasOutLineColor)ce).OutLineWidth = w;
						ChangeObjectProperty(fe,ce);
					}
				}
				GroupEnd();
			}
		}
		// *****************
		public void ChangePriority(FigureElementList fel,int pri)
		{ // オブジェクトの描画順を変更するイベント
			FigureElement fe,ce;
			if (fel.Count > 0){
				IEnumerator enume = fel.GetEnumerator();
				GroupStart();
				while(enume.MoveNext())
				{
					fe = (FigureElement)enume.Current;
					fe.createCopy(out ce);
					ce.Priority = pri;
					ChangeObjectProperty(fe,ce);
				}
				GroupEnd();
			}
		}
//		// *****************
//		public FigureElement ChangePriority(FigureElement element,int pri)
//		{ // オブジェクトの描画順を変更するイベント．今は簡易実装のため，オブジェクトを作り直す．
//			FigureElement ce;
//			element.createCopy(out ce);
//			ce.Priority = pri;
//			ChangeObjectProperty(element,ce);
//			return ce;
//		}
		// *****************
		public FigureElement ChangePriorityDeepest(FigureElement element)
		{ // オブジェクトの描画順を変更するイベント．今は簡易実装のため，オブジェクトを作り直す．
			FigureElement ce;
			element.createCopy(out ce);
			ce.Priority = FigureElement.GetNewMinPriority();
			ChangeObjectProperty(element,ce);
			return ce;
		}
		// *****************
		public FigureElement ChangePriorityShallowest(FigureElement element)
		{ // オブジェクトの描画順を変更するイベント．今は簡易実装のため，オブジェクトを作り直す．
			FigureElement ce;
			element.createCopy(out ce);
			ce.Priority = FigureElement.GetNewMaxPriority();
			ChangeObjectProperty(element,ce);
			return ce;
		}
		// ******************
		public void ChangeFont(FigureElementList fel,Color c,Font f)
		{ // テキスト属性をもつ要素のフォントを変更する
			FigureElement fe,ce;
			IEnumerator enume = fel.GetEnumerator();
			bool flag = false;
			while(enume.MoveNext())
			{
				if (enume.Current is IHasText) 
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				GroupStart();
				enume = fel.GetEnumerator();
				while(enume.MoveNext())
				{
					if (enume.Current is IHasText)
					{
						fe = (FigureElement)enume.Current;
						fe.createCopy(out ce);
						((IHasText)ce).FillColor = c;
						((IHasText)ce).Font = f;
						ChangeObjectProperty(fe,ce);
					}
				}
				GroupEnd();
			}
		}
		// *******************
		public void ChangeText(TextElement te,string s)
		{ // テキストの文章を変更するイベント
			FigureElement ce;
			te.createCopy(out ce);
			((IHasText)ce).Text = s;
			ChangeObjectProperty(te,ce);
		}
		// ***************
		protected void ChangeObjectProperty(FigureElement before,FigureElement after)
		{// 矢印の引継ぎなどをしつつ、オブジェクトの色などの情報を変更するイベントを作る。
			// 実際はオブジェクトをeraseしてcreateしなおす。
			FigureElementList fromList,towardList;
			GroupStart();
			//まず新しいエレメントを生成するイベントを生成。
			CreateObjectEvent coe;
			after.createCreateEvent(elementList,out coe);
			insertEvent(coe);
			Do();
			//次に関連矢印を更新。
			if ((before is ArrowElement) == false)
			{
				// 変更する矢印リストを得る。
				fromList = new FigureElementList();
				towardList = new FigureElementList();
				elementList.GetArrowPointedListOf(before,ref fromList,ref towardList);
				// 新しいエレメントをコピーする。
				ArrowElement ae,aae;
				FigureElement ce;
				IEnumerator enume = fromList.GetEnumerator();
				while(enume.MoveNext())
				{
					ae = (ArrowElement)enume.Current;
					ae.createCopy(out ce);
					aae = (ArrowElement)ce;
					aae.fromElement = after;
					ChangeObjectProperty(ae,aae);
				}
				enume = towardList.GetEnumerator();
				while(enume.MoveNext())
				{
					ae = (ArrowElement)enume.Current;
					ae.createCopy(out ce);
					aae = (ArrowElement)ce;
					aae.towardElement = after;
					ChangeObjectProperty(ae,aae);
				}
				// 資源開放
				fromList.Clear();
				towardList.Clear();
			}
			EraseObject(elementList.IndexOf(before));
			GroupEnd();
			//updateDrawList();
		}
// ************
		public void RecogObjects(FigureElementList felo)
		{
			if (felo.Count>0)
			{
				GroupStart();
				IEnumerator enume = felo.GetEnumerator();
				RecogGroupElement rge;
				while(enume.MoveNext())
				{
					if (enume.Current is RecogGroupElement)
					{
						rge = (RecogGroupElement)enume.Current;
						RecogObject(rge);
					}
				}
				GroupEnd();
			}
		}
		public void RecogObject(RecogGroupElement rge)
		{ // 認識オブジェクトを認識後の姿に変化させる。
			ObjectEvent oe= new RecognizeRecogGroupEvent(elementList,rge);
			insertEvent(oe);
			Do();
			//updateDrawList();
		}
// ***********
		public FigureElement CreateRecogGroup(int prio,FigureElementList beforeList,FigureElementList afterList)
		{ // 認識オブジェクトを作る。
			ObjectEvent oe= new CreateRecogGroupEvent(elementList,parentControl,prio,beforeList,afterList);
			insertEvent(oe);
			Do();
			//updateDrawList();
			return oe.figureElement;
		}

// ************   Load & Save ************************
		public void Load(string slidefile)
		{
			try
			{
				Stream stream = File.OpenRead(slidefile);
				Load(stream,Path.GetDirectoryName(slidefile));
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide Load Error.",e.ToString());
			}
		}
		public void Load(Stream _stream,string linkBaseDir)
		{
            FigureElement fe;
//			string rawFileName = QBasic.Util.getFileNameWithoutPath(slidefile);
//			string slidePath = slidefile.Replace("\\" + rawFileName,"");
			clearAll();
			elementList.EnableListChanged = false;


            ProgressBarForm pbf = new ProgressBarForm(Util.IsPropertyTrue("Base.English") ? "Loading..." : "ファイルを読み込んでいます…");
			pbf.ProgressBar.Value = 50;
			pbf.Show();
			pbf.Refresh();
			try
			{
				//XmlTextReader xtr = new XmlTextReader(slidefile);
				XmlTextReader xtr = new XmlTextReader(_stream);
				xtr.WhitespaceHandling = WhitespaceHandling.None;

				EVENT eventType;
				string eN = null;
				string eV = null ;
				Rectangle r = new Rectangle();
				int s_x,s_y,e_x,e_y;
				Color c,oc;
				int ow;
				int dashStyle,num,index;
				ArrayList indexList = new ArrayList();
				ArrayList indexList2 = new ArrayList();
				int versionID = 0;
				int prio;
				int id;


				// init viewSnapList
				//viewSnapList.ProbeLoadInit();
				viewSnapListTable.Clear();

				// ここまではnet環境でも問題なし
				while (xtr.Read() == true)
				{

					if (xtr.NodeType == XmlNodeType.Element && xtr.Name.Equals("Version"))
					{
						xtr.Read();
						string version = xtr.Value;
						if (version.Equals("KOTODAMA2.2"))
						{
							versionID = 22;
						}
						else if (version.Equals("KOTODAMA2.5"))
						{
							versionID = 25;
						}
                        else if (version.Equals("KOTODAMA3.0") || version.Equals("KOTODAMA3.1"))
						{
							versionID = 30;
						}
                        else if (version.Equals("KOTODAMA3.2"))
                        {
                            versionID = 32;
                        }
                        else if (version.Equals("KOTODAMA3.3"))
                        {
                            versionID = 33; // LinkImageElementを加えただけなのでそれほど問題ない
                        }
                    }
					if (xtr.NodeType == XmlNodeType.Element && xtr.Name.Equals("Size"))
					{
						int tmp;
						readSec(xtr,ref eN,ref eV); // Width
						tmp = Convert.ToInt32(eN);
						slideSize.Width = tmp;
						readSec(xtr,ref eN,ref eV); // Height
						tmp = Convert.ToInt32(eN);
						slideSize.Height = tmp;
                        // slideSizeに基づきparentControl.ClientSizeを変更することを期待するイベント
                        if (SlideSizeInvalidated != null) SlideSizeInvalidated(this, new EventArgs());
                        //view.ScreenSize = parentControl.ClientSize;
					}
					//ViewSnapList
					ViewSnapList newList = ViewSnapList.ProbeLoad(xtr,view);
					if (newList != null)
					{
						//add hashtable of viewsnaplist, key = id
						viewSnapListTable.Add(newList.Id,newList);
					}
					//ink
					if (xtr.NodeType == XmlNodeType.Element && xtr.Name.Equals("Ink"))
					{
						xtr.Read();
						string inkRaw = xtr.Value;
						string ink;
						if (versionID >=25)
						{
							//ink = System.Web.HttpUtility.HtmlDecode(inkRaw);
							ink = inkRaw;
						}
						else
						{
							ink = inkRaw;
						}
						
						// This object will encode our byte data to a UTF8 string
						UTF8Encoding utf8 = new UTF8Encoding();
						// load the ink into a new ink object
						// once an ink object has been "dirtied" it can never load ink again
						//StrokeElement.inkCollector.Ink.Load(utf8.GetBytes(ink));
						StrokeElement.Load(utf8.GetBytes(ink));
					}
					if (xtr.NodeType == XmlNodeType.Element && xtr.Name.Equals("Event"))
					{
						prio = -1;// default setting
						xtr.Read();
						readSec(xtr,ref eN,ref eV); // Element Type
						eventType = (EVENT)Convert.ToInt32(eN);
						readSec(xtr,ref eN,ref eV); // Element Time (ignore)
						switch (eventType)
						{
							case EVENT.ERASE_OBJECT:
								readSec(xtr,ref eN,ref eV); // Element ObjectID
								__EraseObject(Convert.ToInt32(eN));// 内部用を呼び出している。
								break;
							case EVENT.MOVE_OBJECT:
								int Mid,Mx,My;
								readSec(xtr,ref eN,ref eV); // Element ObjectID
								Mid = Convert.ToInt32(eN);
								readSec(xtr,ref eN,ref eV); // Element X
								Mx = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Y
								My = (int)(Convert.ToInt32(eN));
								MoveObject(Mid,Mx,My);
								break;
							case EVENT.CREATE_RECTANGLE:
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Color (int argb)
								c = Color.FromArgb(Convert.ToInt32(eN));
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element OutColor (int argb)
									oc = Color.FromArgb(Convert.ToInt32(eN));
									readSec(xtr,ref eN,ref eV); // Element OutWidth
									ow = Convert.ToInt32(eN);
								}
								else
								{
									oc = Color.Black;
									ow = 0;
								}
								fe = createRectangle(prio,r,c,oc,ow);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }

								break;
							case EVENT.CREATE_ELLIPSE:
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Color (int argb)
								c = Color.FromArgb(Convert.ToInt32(eN));
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element OutColor (int argb)
									oc = Color.FromArgb(Convert.ToInt32(eN));
									readSec(xtr,ref eN,ref eV); // Element OutWidth
									ow = Convert.ToInt32(eN);
								}
								else
								{
									oc = Color.Black;
									ow = 0;
								}
								fe = createEllipse(prio,r,c,oc,ow);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }

								break;
							case EVENT.CREATE_TEXT:
								string str,fontn;
								int sty;
								Font font;
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Text
								str = eN;
								if (str !="")
								{
									readSec(xtr,ref eN,ref eV); // Element Color (int argb)
									c = Color.FromArgb(Convert.ToInt32(eN));
									readSec(xtr,ref eN,ref eV); // Element FontName
									fontn = eN;
									readSec(xtr,ref eN,ref eV); // Element FontStyle (int)
									sty = Convert.ToInt32(eN);
									font = new Font(fontn,16,(FontStyle)sty);
									fe = createText(prio,r,str,c,font);
									//								createText(r,eN);
                                    if (versionID >= 32)
                                    {
                                        LoadTag(xtr, fe);
                                    }

								}
								break;
							case EVENT.CREATE_ARROW:
								int Af,At;
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element X
								Af = Convert.ToInt32(eN);
								readSec(xtr,ref eN,ref eV); // Element Y
								At = Convert.ToInt32(eN);
								readSec(xtr,ref eN,ref eV); // Element Color (int argb)
								c = Color.FromArgb(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element DashStyle (int)
								dashStyle = Convert.ToInt32(eN);
								fe = createArrow(prio,Af,At,c,(System.Drawing.Drawing2D.DashStyle)dashStyle);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }

								break;
							case EVENT.CREATE_BITMAP:
							case EVENT.CREATE_SCRATCH:
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element File or Image(serialized) eN
								if (versionID >= 25)
								{// 画像は全てシリアライズ版．
//									string tmpPath = System.IO.Path.GetTempFileName();
//									StreamWriter sw = new StreamWriter(tmpPath);
//									System.Web.HttpUtility.HtmlDecode(eN,sw);
//									sw.Close();
//									Stream stream = File.OpenRead(tmpPath);
//									SoapFormatter soapFormatter = new SoapFormatter();
//									Bitmap bm = (Bitmap)soapFormatter.Deserialize(stream);
//									stream.Close();
//									try
//									{
//										File.Delete(tmpPath);
//									}
//									catch(Exception e)
//									{
//									}

									Bitmap bm = null;
                                    //if (Qurihara.QBasic.Util.IsPropertyTrue("Base.LocalApp"))
                                    //{

                                    if (versionID >= 32)
                                    {
                                        bm = QBasic.DrawingUtil.BitmapBase64Deserialize(eN);
                                    }
                                    else
                                    {
                                        //SoapFormatterとHtmlDecodeでsecurityエラーが出るので、別関数に移す。
                                        bm = QBasic.DrawingUtil.SOAPDeserialize(eN);
                                    }
                                    //}
                                    //else
                                    //{
                                    //    NetSerializerProxy.NetSerializerProxy serial = new NetSerializerProxy.NetSerializerWeb("pass");
                                    //    byte [] b = serial.ImageDeserializer(eN);
                                    //    MemoryStream stream = new MemoryStream(b);
                                    //    Image im = Image.FromStream(stream);
                                    //    bm = new Bitmap(im);
                                    //}

									if (eventType == EVENT.CREATE_BITMAP)
									{
										fe = createBitmap(prio,r,bm);
                                        if (versionID >= 32)
                                        {
                                            LoadTag(xtr, fe);
                                        }

									}
									else
									{ // case of EVENT.CREATE_SCRATCH
										fe = createScratch(prio,r,bm);
                                        if (versionID >= 32)
                                        {
                                            LoadTag(xtr, fe);
                                        }

									}
								}
								else
								{

//									string path = null;
//									if (QBasic.Util.IsFileNameWithoutPath(eN))
//									{//相対パスならば、スライドと同じディレクトリ。
//										path = slidePath + "\\" + eN;
//									}
//									else
//									{
//										path = eN;
//									}
////									if (!System.IO.File.Exists(path))
////									{
////										path = Slide.noLinkImageFileName;
////									}
//									if (System.IO.File.Exists(path))
//									{
//										if (eventType == EVENT.CREATE_BITMAP)
//										{
//											createBitmap(prio,r,path);
//										}
//										else
//										{ // case of EVENT.CREATE_SCRATCH
//											createScratch(prio,r,path);
//										}
//									}
								}
								break;
							case EVENT.CREATE_INK:
								// InkはBitmapに変換されるのでここには来ない。
								break;
							case EVENT.CREATE_LINE:
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Start_X
								s_x= (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Start_Y
								s_y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element End_X
								e_x = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element End_Y
								e_y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Color (int argb)
								c = Color.FromArgb(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element DashStyle (int)
								dashStyle = Convert.ToInt32(eN);
								fe = createLine(prio,r,s_x,s_y,e_x,e_y,c,(System.Drawing.Drawing2D.DashStyle)dashStyle);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }

								break;
							case EVENT.RESIZE_OBJECT:
								int Rid,Rx,Ry,Rw,Rh;
								readSec(xtr,ref eN,ref eV); // Element ObjectID
								Rid = Convert.ToInt32(eN);
								readSec(xtr,ref eN,ref eV); // Element X
								Rx = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Y
								Ry = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element W
								Rw = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element H
								Rh = (int)(Convert.ToInt32(eN));
								ResizeObject(Rid,Rx,Ry,Rw,Rh);
								break;
							case EVENT.CREATE_EXTERNAL:
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element File
								
                                //絶対パスに変換
                                string eND = System.Web.HttpUtility.UrlDecode(eN);
                                Uri path;
                                if (linkBaseDir != "")
                                {
                                    if (!linkBaseDir.EndsWith("\\")) linkBaseDir += "\\";
                                    Uri basePath = new Uri(linkBaseDir);
                                    path = new Uri(basePath,
                                        eND);
                                }
                                else
                                {
                                    path = new Uri(eND);
                                }
                                fe = createExternal(prio, r, path.LocalPath);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }


//								string fileToCheck;
//								string [] xtmp;
//								bool isMacro = ExternalElement.IsMacroExternalElement(eN,out xtmp);
//								if (QBasic.Util.IsFileNameWithoutPath(eN)
//									&& !isMacro)
//								{//相対パスならば、スライドと同じディレクトリ。
//									fileToCheck = slidePath + "\\" + eN;
//								}
//								else
//								{
//									fileToCheck = eN;
//								}
//								if (System.IO.File.Exists(fileToCheck) || isMacro)
//								{
//									createExternal(prio,r,fileToCheck);
//								}
//								else
//								{ // ファイルがない。
//									//string noLinkStr = " --- <NO LINK>";
//									string noLinkStr = "[NOLINK]";
//									if (!fileToCheck.EndsWith(noLinkStr))
//										fileToCheck = noLinkStr + fileToCheck;
//										//fileToCheck += noLinkStr;
//									createExternal(prio,r,fileToCheck);
//								}
//								createExternal(prio,r,eN);
								break;
                            case EVENT.CREATE_LINK_IMAGE:
                                readSec(xtr, ref eN, ref eV); // Element Priority
                                prio = Convert.ToInt32(eN);
                                readSec(xtr, ref eN, ref eV); // Element Rect_X
                                r.X = (int)(Convert.ToInt32(eN));
                                readSec(xtr, ref eN, ref eV); // Element Rect_Y
                                r.Y = (int)(Convert.ToInt32(eN));
                                readSec(xtr, ref eN, ref eV); // Element Rect_W
                                r.Width = (int)(Convert.ToInt32(eN));
                                readSec(xtr, ref eN, ref eV); // Element Rect_H
                                r.Height = (int)(Convert.ToInt32(eN));
                                readSec(xtr, ref eN, ref eV); // Element File

                                eND = System.Web.HttpUtility.UrlDecode(eN);
                                //Uri path = new Uri(eND);

                                string hash = "";
                                xtr.Read();
                                if (!xtr.IsEmptyElement)
                                {
                                    xtr.Read(); // tag
                                    hash = System.Web.HttpUtility.HtmlDecode(xtr.Value);
                                    xtr.Read(); // endElement
                                }

                                readSec(xtr, ref eN, ref eV); // refleshrate
                                int refle = int.Parse(eN);
                                readSec(xtr, ref eN, ref eV); // persist
                                bool per = bool.Parse(eN);

                                fe = createLinkImage(prio, r,eND,hash,refle,per);
                                LoadTag(xtr, fe);
                                break;
                            case EVENT.GROUP_START:
								GroupStart();
								break;
							case EVENT.GROUP_END:
								GroupEnd();
								break;
							case EVENT.CREATE_ELEMENT_GROUP:
								if (versionID >= 22)
								{
									readSec(xtr,ref eN,ref eV); // Element Priority
									prio = Convert.ToInt32(eN);
								}
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // ElementNum
								num = Convert.ToInt32(eN);
								xtr.Read(); // Elements

								for(int i=0;i<num;i++)
								{
									readSec(xtr,ref eN,ref eV); // ElementID
									index = Convert.ToInt32(eN);
									indexList.Add(index);
								}
								xtr.Read(); // Elements
								fe = createElementGroup(prio,indexList);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }

								indexList.Clear();
								break;
							case EVENT.RELEASE_ELEMENT_GROUP:
								readSec(xtr,ref eN,ref eV); // Element ObjectID
								ReleaseElementGroup(Convert.ToInt32(eN));
								break;
							case EVENT.CREATE_STROKE:
								readSec(xtr,ref eN,ref eV); // Element Priority
								prio = Convert.ToInt32(eN);
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));

								readSec(xtr,ref eN,ref eV); // Element ID
								id = Convert.ToInt32(eN);

								//createStroke(prio,r,id);

								StrokeElement sele = (StrokeElement)createStroke(prio,r,id);
								// なんらかの原因（主に不手際）でインクとオブジェクトのBoundingBoxがずれたときにこれらを同期させる。
								sele.SynchronizeBoundingBox();
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, sele);
                                }

								break;
							case EVENT.CREATE_RECOG_GROUP:
								readSec(xtr,ref eN,ref eV); // Element Priority
								prio = Convert.ToInt32(eN);
								readSec(xtr,ref eN,ref eV); // Element Rect_X
								r.X = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_Y
								r.Y = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_W
								r.Width = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // Element Rect_H
								r.Height = (int)(Convert.ToInt32(eN));
								readSec(xtr,ref eN,ref eV); // PreElementNum
								num = Convert.ToInt32(eN);
								xtr.Read(); // preElements

								for(int i=0;i<num;i++)
								{
									readSec(xtr,ref eN,ref eV); // ElementID
									index = Convert.ToInt32(eN);
									indexList.Add(index);
								}
								xtr.Read(); // preElements
								readSec(xtr,ref eN,ref eV); // PostElementNum
								num = Convert.ToInt32(eN);
								xtr.Read(); // PostElements

								for(int i=0;i<num;i++)
								{
									readSec(xtr,ref eN,ref eV); // PostElementID
									index = Convert.ToInt32(eN);
									indexList2.Add(index);
								}
								xtr.Read(); // PostElements

								fe = createRecogGroup(prio,indexList,indexList2);
                                if (versionID >= 32)
                                {
                                    LoadTag(xtr, fe);
                                }

								createElementGroup(prio,indexList);
								indexList.Clear();
								indexList2.Clear();
								break;
							case EVENT.RECOG_RECOG_GROUP:
								readSec(xtr,ref eN,ref eV); // Element ObjectID
								RecogObject(Convert.ToInt32(eN));
								break;
							default:
								// unable to reach here
								System.Diagnostics.Debug.Fail("Slide load error.");
								break;
						}
					
					}
					//Application.DoEvents();

				}
				xtr.Close();
				//Application.DoEvents();
				//System.GC.Collect();

                dirty = false;

				ViewSnapList list = (ViewSnapList)viewSnapListTable["default"];
				if (list != null)
				{
					if (list.Count >0) ((ViewSnap)list[0]).Warp();
				}
                if (SlideLoaded != null) SlideLoaded(this,new EventArgs());

				elementList.EnableListChanged = true;
				updateDrawList();
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide File Load Error.",e.ToString());
			}
			pbf.Hide();
			pbf.Dispose();
		}

        private void LoadTag(XmlTextReader x, FigureElement fe)
        {
            x.Read();
            if (!x.IsEmptyElement) {
                x.Read(); // tag
                fe.Tag = System.Web.HttpUtility.HtmlDecode(x.Value);
                x.Read(); // endElement
            }
        }

		private void readSec(XmlTextReader x,ref string n,ref string v)
		{
			x.Read(); // Element Type
			n = x.Name;
			x.Read(); // Text  Type
			n = x.Value;
			x.Read(); // endElement		
		}

		// debug functions
		private XmlTextReader xtrt;
		public void testload(string slidefile)
		{
			xtrt = new XmlTextReader(slidefile);
			xtrt.WhitespaceHandling = WhitespaceHandling.None;
		}
		public bool testread(ref string e)
		{
			if (xtrt.Read() == true)
			{
				 e = xtrt.NodeType.ToString() + " | " + xtrt.Name.ToString() + " | " + xtrt.Value.ToString();
				return true;
			}
			else
			{
				return false;
			}
		}
		/*
		public bool SaveAsBitmap(Bitmap bm,float ratio)
		{
			return SaveAsBitmap(bm,DefaultDirectory + "\\" + name + ".ks.png",ratio);
		}
		*/
//		public bool SaveAsBitmap(Bitmap bm,string bitmapfile,float ratio)
//		{
//			try
//			{
//				System.IO.Stream st = System.IO.File.OpenWrite(bitmapfile);
//
//				//インクを書き込む 削除したオブジェクトまで書き込んでしまうので廃止した．
//				//QBasic.InkUtil.Strokes2Bitmap(ref bm,ratio,ratio,StrokeElement.inkCollector,StrokeElement.inkCollector.Ink.Strokes);
//
//				// Graphics作成
//				Graphics tg = Graphics.FromImage(bm);
//
////				//インク倍率変更用Matrix
////				Matrix m = new Matrix();
////				Matrix wm = new Matrix();
////
////				//tg.TranslateTransform(100,100,MatrixOrder.Append);  これはどういう意味なのだろう？
////				// 現在のMatrixを保存
////				StrokeElement.inkCollector.Renderer.GetViewTransform(ref wm);
////
////				// 倍率変換
////				m.Scale(ratio,ratio);
////				StrokeElement.inkCollector.Renderer.SetViewTransform(m);
////			
////				// 縮小するように変換。
////				tg.ScaleTransform(ratio,ratio);
////
////				// オブジェクト書き込み
////				this.draw(tg,false);
////				//this.drawWithoutInk(tg,false);
////
////				// Matrixを復元
////				StrokeElement.inkCollector.Renderer.SetViewTransform(wm);
////				m.Dispose();
////				wm.Dispose();
//
//				Rectangle prevViewRect = View.ViewRectangle;
//				if (ElementList.Count > 0)
//				{
//					// viewを全体viewへ
//					Rectangle r = new Rectangle(0,0,0,0);
//					ElementList.GetBoundingBox(ref r);
//
//					float aspect = (float)View.ScreenSize.Width
//						/ (float)View.ScreenSize.Height;
//					Rectangle re = Qurihara.QBasic.DrawingUtil.GetRectangleInAspectOf(aspect,r);
//					re.Width = (int)(re.Width/ratio);
//					re.Height = (int)(re.Height/ratio);
//
//					View.ViewRectangle = re;
//
//					//書き込み
//					draw(tg,true);
//					// viewをもとにもどす
//					View.ViewRectangle = prevViewRect;
//				}
//				//tg.SmoothingMode= System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
//				
//				// 画像をファイルに保存
//				bm.Save(st,System.Drawing.Imaging.ImageFormat.Png);
//				// ファイルを閉じる
//				st.Close();
//				tg.Dispose();
//			}
//			catch(System.Exception e)
//			{
//				System.Diagnostics.Debug.Fail("Slide Bitmap Save error.",e.ToString());
//			}
//			return true;
//		}
		public bool SaveOriginAsBitmap(Bitmap bm,string bitmapfile,float ratio)
		{
			// viewを原点viewへ
			Rectangle r = new Rectangle(0,0,View.ScreenSize.Width,View.ScreenSize.Height);
			return SaveAsBitmap(bm,bitmapfile,ratio,r);
		}
		public bool SaveAllAsBitmap(Bitmap bm,string bitmapfile,float ratio)
		{
			// viewを全体viewへ
			Rectangle r = new Rectangle(0,0,0,0);
			ElementList.GetBoundingBox(ref r);

			float aspect = (float)View.ScreenSize.Width
				/ (float)View.ScreenSize.Height;
			Rectangle re = Qurihara.QBasic.DrawingUtil.GetRectangleInAspectOf(aspect,r);

			return SaveAsBitmap(bm,bitmapfile,ratio,re);
		}
		public bool SaveAsBitmap(Bitmap bm,string bitmapfile,float ratio,Rectangle viewToSave)
		{
			try
			{
				Stream stream = File.OpenWrite(bitmapfile);
				return SaveAsBitmap(bm,stream,ratio,viewToSave);
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide Bitmap Save Error.",e.ToString());
				return false;
			}
		}
		public bool SaveAsBitmap(Bitmap bm,Stream st,float ratio,Rectangle viewToSave)
		{
			try
			{
				//System.IO.Stream st = System.IO.File.OpenWrite(bitmapfile);

				//インクを書き込む 削除したオブジェクトまで書き込んでしまうので廃止した．
				//QBasic.InkUtil.Strokes2Bitmap(ref bm,ratio,ratio,StrokeElement.inkCollector,StrokeElement.inkCollector.Ink.Strokes);

				// Graphics作成
				Graphics tg = Graphics.FromImage(bm);

				Rectangle prevViewRect = View.ViewRectangle;
				if (ElementList.Count > 0)
				{
					Rectangle re = viewToSave;
					re.Width = (int)(re.Width/ratio);
					re.Height = (int)(re.Height/ratio);

					bool changed = false;
					if (!viewToSave.Equals(View.ViewRectangle))
					{
						View.ViewRectangle = re;
						changed = true;
					}
					//書き込み
					draw(tg,true);

					if (changed)
					{
						// viewをもとにもどす
						View.ViewRectangle = prevViewRect;
					}
				}
				//tg.SmoothingMode= System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
				
				// 画像をファイルに保存
				bm.Save(st,System.Drawing.Imaging.ImageFormat.Png);
				// ファイルを閉じる
				st.Close();
				tg.Dispose();
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide Bitmap Save error.",e.ToString());
			}
			return true;
		}
		public bool SaveAsNewBitmap(Stream st,Size bitmapSize,Rectangle viewToSave)
		{
			try
			{
				Bitmap bm = new Bitmap(bitmapSize.Width,bitmapSize.Height);
				Graphics tg = Graphics.FromImage(bm);
				tg.FillRectangle(new SolidBrush(Color.White),0,0,bitmapSize.Width,bitmapSize.Height);

				Rectangle prevViewRect = View.ViewRectangle;
				Size prevScreenSize = View.ScreenSize;
				if (ElementList.Count > 0)
				{
					Rectangle re = viewToSave;
					View.ScreenSize = bitmapSize;

					bool changed = false;
					if (!viewToSave.Equals(View.ViewRectangle))
					{
						View.ViewRectangle = re;
						changed = true;
					}
					//書き込み
					tg.SmoothingMode= System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
					draw(tg,true);

					if (changed)
					{
						// viewをもとにもどす
						View.ViewRectangle = prevViewRect;
					}
					View.ScreenSize = prevScreenSize;
				}
				
				// 画像をファイルに保存
				bm.Save(st,System.Drawing.Imaging.ImageFormat.Png);
				// ファイルを閉じる
				st.Close();
				tg.Dispose();
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide Bitmap Save error.",e.ToString());
			}
			return true;
		}

		/*
		public bool SaveAsXml(bool package)
		{
			return SaveAsXml(DefaultDirectory + "\\" + name + ".ks.xml",package);
		}
		*/
		public bool SaveAsXml(string slidefile,bool package)
		{
			try
			{
				Stream stream = File.OpenWrite(slidefile);
				return SaveAsXml(stream,package, Path.GetDirectoryName(slidefile));
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide Save Error.",e.ToString());
				return false;
			}
		}
		//public bool SaveAsXml(string slidefile, bool package)
		public bool SaveAsXml(Stream _stream, bool package,string linkBaseDir)
		{
			ProgressBarForm pbf = new ProgressBarForm("ファイルを書き出しています…");
			pbf.ProgressBar.Value = 50;
			pbf.Show();
			pbf.Refresh();

			ArrayList indexList = new ArrayList();

			int positionToSave = currentPosition;
			while(UnDo()); // スライドのイベントを巻き戻す。ReDoの途中でもすべてのイベントを書き込む仕様。
			try
			{
				//XmlTextWriter xtw = new XmlTextWriter(slidefile,null);
				XmlTextWriter xtw = new XmlTextWriter(_stream,Encoding.UTF8);
				xtw.Formatting = Formatting.Indented;
				xtw.Indentation = 3;
				xtw.WriteStartDocument();
				xtw.WriteStartElement("Slide");
				//xtw.WriteElementString("Version","KOTODAMA2.2");
				//xtw.WriteElementString("Version","KOTODAMA2.5");
				//xtw.WriteElementString("Version","KOTODAMA3.0");
                //xtw.WriteElementString("Version", "KOTODAMA3.1");
                //xtw.WriteElementString("Version", "KOTODAMA3.2");// 080125
                xtw.WriteElementString("Version", "KOTODAMA3.3");// 080328
                xtw.WriteStartElement("Size");
                xtw.WriteElementString("Width", slideSize.Width.ToString());
                xtw.WriteElementString("Height", slideSize.Height.ToString());
                //xtw.WriteElementString("Width",1024.ToString());
                //xtw.WriteElementString("Height",692.ToString());
				xtw.WriteEndElement(); // Size
				
				// ViewSnapList
				IDictionaryEnumerator denume = viewSnapListTable.GetEnumerator();
                //bool first = true;
				while(denume.MoveNext())
				{
					ViewSnapList list = denume.Value as ViewSnapList;
					list.Save(xtw);
                    //if (first && list.Count > 0)
                    //{
                    //    first = false;
                    //    ViewSnap vs = (ViewSnap)list[0];
                    //    int wd = vs.ViewRectangle.Width;
                    //    int hg = vs.ViewRectangle.Height;
                    //    xtw.WriteStartElement("Size");
                    //    xtw.WriteElementString("Width",wd.ToString());
                    //    xtw.WriteElementString("Height",hg.ToString());
                    //    xtw.WriteEndElement(); // Size
                    //}
				}
				//viewSnapList.Save(xtw);


				// This object will encode our byte data to a UTF8 string
				UTF8Encoding utf8 = new UTF8Encoding();            
				byte[] base64ISF_bytes;
				string base64ISF_string;
				// Get the base64 encoded ISF
				base64ISF_bytes = StrokeElement.inkCollector.Ink.Save(PersistenceFormat.Base64InkSerializedFormat);
				// Convert it to a String
				char [] nul = {'\0'};
				base64ISF_string = utf8.GetString(base64ISF_bytes).TrimEnd(nul);
				// Write the ISF containing node to the XML
				// 051110 htmlEncodeで暗号化 version2.5
				//xtw.WriteElementString("Ink", System.Web.HttpUtility.HtmlEncode(base64ISF_string));
				xtw.WriteElementString("Ink", base64ISF_string);

				elementList.EnableListChanged = false;
				elementList.Clear();

				IEnumerator enume = eventList.GetEnumerator();
				IEvent ie;
				string pfilename =null;
				while (enume.MoveNext())
				{
                    if (positionToSave > 0)
                    {
                        pbf.ProgressBar.Value = currentPosition * 100 / positionToSave;
                        pbf.Refresh();
                    }

					xtw.WriteStartElement("Event");
					ie =(IEvent)enume.Current;
					xtw.WriteComment(ie.Type.ToString());

					if (ie.Type != EVENT.CREATE_INK)
					{
						xtw.WriteElementString("Type",Convert.ToInt32(ie.Type).ToString());
					}
					else
					{ // InkのときはBitmapで書き込む もしくはScratch
						//if(((ObjectEvent)ie).figureElement is BitmapElement)
						if(ie is ObjectEvent && ((ObjectEvent)ie).figureElement is ScratchElement)
						{ // case of ScratchElement
							xtw.WriteElementString("Type",Convert.ToInt32(EVENT.CREATE_SCRATCH).ToString());
						}
						else
						{ // case of BitmapElement
							xtw.WriteElementString("Type",Convert.ToInt32(EVENT.CREATE_BITMAP).ToString());
						}
					}
					xtw.WriteElementString("Time",ie.TimeStamp.ToString());
					switch (ie.Type)
					{
						case EVENT.ERASE_OBJECT:
						case EVENT.RELEASE_ELEMENT_GROUP:
						case EVENT.RECOG_RECOG_GROUP:
							EraseObjectEvent ee = (EraseObjectEvent)ie;
							xtw.WriteElementString("ObjectID", ee.getID().ToString());
							Do(); // このイベントは、IDを得るために後からDoする。
							break;
						case EVENT.MOVE_OBJECT:
							Do();
							MoveObjectEvent me = (MoveObjectEvent)ie;
							xtw.WriteElementString("ObjectID", me.getID().ToString());
							xtw.WriteElementString("X", me.X.ToString());
							xtw.WriteElementString("Y", me.Y.ToString());
							break;
						case EVENT.CREATE_RECTANGLE:
							Do();
							CreateRectangleEvent re = (CreateRectangleEvent)ie;
							xtw.WriteElementString("Priority",re.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", re.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", re.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", re.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", re.figureElement.BoundingBox.Height.ToString());
							xtw.WriteElementString("Color",((RectangleElement)re.figureElement).FillColor.ToArgb().ToString());
							xtw.WriteElementString("OutColor",((RectangleElement)re.figureElement).OutLineColor.ToArgb().ToString());
							xtw.WriteElementString("OutWidth",((RectangleElement)re.figureElement).OutLineWidth.ToString());
                            WriteTag(xtw, re.figureElement);
                            break;
						case EVENT.CREATE_ELLIPSE:
							Do();
							CreateEllipseEvent Ee = (CreateEllipseEvent)ie;
							xtw.WriteElementString("Priority",Ee.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", Ee.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", Ee.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", Ee.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", Ee.figureElement.BoundingBox.Height.ToString());
							xtw.WriteElementString("Color",((EllipseElement)Ee.figureElement).FillColor.ToArgb().ToString());
							xtw.WriteElementString("OutColor",((EllipseElement)Ee.figureElement).OutLineColor.ToArgb().ToString());
							xtw.WriteElementString("OutWidth",((EllipseElement)Ee.figureElement).OutLineWidth.ToString());
                            WriteTag(xtw, Ee.figureElement);
                            break;
						case EVENT.CREATE_TEXT:
							Do();
							CreateTextEvent te = (CreateTextEvent)ie;
							xtw.WriteElementString("Priority",te.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", te.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", te.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", te.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", te.figureElement.BoundingBox.Height.ToString());
							xtw.WriteElementString("Text", ((TextElement)te.figureElement).Text);
							//
							xtw.WriteElementString("Color",((TextElement)te.figureElement).FillColor.ToArgb().ToString());
							xtw.WriteElementString("FontName",((TextElement)te.figureElement).Font.Name);
							xtw.WriteElementString("FontStyle",((int)((TextElement)te.figureElement).Font.Style).ToString());
                            WriteTag(xtw, te.figureElement);

							break;
						case EVENT.CREATE_ARROW:
							Do();
							CreateArrowEvent ae = (CreateArrowEvent)ie;
							xtw.WriteElementString("Priority",ae.figureElement.Priority.ToString());
							int fro=-1, towa=-1;
							ae.getEdgesID(ref fro, ref towa);
							if (fro < 0 || towa < 0 ) 
							{
								// 矢印の端が無いエラー
								System.Diagnostics.Debug.Fail("Slide Save error. Arrow edge not found");
							}
							xtw.WriteElementString("FromID", fro.ToString());
							xtw.WriteElementString("TowardID", towa.ToString());
							xtw.WriteElementString("Color",((ArrowElement)ae.figureElement).FillColor.ToArgb().ToString());
							xtw.WriteElementString("DashStyle",((int)((ArrowElement)ae.figureElement).dashStyle).ToString());
                            WriteTag(xtw, ae.figureElement);
                            break;
						case EVENT.CREATE_BITMAP:
						case EVENT.CREATE_SCRATCH:
							Do();
							CreateBitmapEvent be = (CreateBitmapEvent)ie;
							xtw.WriteElementString("Priority",be.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", be.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", be.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", be.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", be.figureElement.BoundingBox.Height.ToString());
                            //if (package)
							if (true)
							{
								
//								string tmpPath = System.IO.Path.GetTempFileName();
//								Stream stream = File.OpenWrite(tmpPath);
//								soapFormatter.Serialize(stream,((BitmapElement)be.figureElement).BitMap);
//								stream.Close();
//
//								StreamReader sr = new StreamReader(tmpPath);
//								string s = sr.ReadToEnd();
//								sr.Close();
//								try
//								{
//									File.Delete(tmpPath);
//								}
//								catch(Exception e)
//								{
//								}

                                //string outs = "";
                                ////if (Qurihara.QBasic.Util.IsPropertyTrue("Base.LocalApp"))
                                ////{
                                //    outs = _setBm(((BitmapElement)be.figureElement).BitMap);
                                ////}
                                ////else
                                ////{
                                ////    NetSerializerProxy.NetSerializerProxy serializer = new NetSerializerProxy.NetSerializerWeb("pass");
                                ////    Bitmap bt = ((BitmapElement)be.figureElement).BitMap;
                                ////    MemoryStream stream = new MemoryStream();
                                ////    bt.Save(stream,System.Drawing.Imaging.ImageFormat.Png);
                                ////    stream.Close();
                                ////    byte [] b = stream.GetBuffer();
                                ////    outs = serializer.ImageSerializer(b);

                                ////}
                                //xtw.WriteElementString("Image", outs);
                                if (QBasic.Util.IsPropertyTrue("Base.HasSerializedBitmap"))
                                {
                                    xtw.WriteElementString("Image", ((BitmapElement)be.figureElement).ImageString);
                                }
                                else
                                {
                                    xtw.WriteElementString("Image",
                                        QBasic.DrawingUtil.BitmapBase64Serialize(
                                            ((BitmapElement)be.figureElement).BitMap));
                                        //QBasic.DrawingUtil.SOAPSerialize(
                                        //    ((BitmapElement)be.figureElement).BitMap));
                                }

//								pfilename = QBasic.Util.getFileNameWithoutPath(be.fileName);
//								if (!System.IO.File.Exists(DefaultDirectory + "\\" + pfilename))
//									System.IO.File.Copy(be.fileName,DefaultDirectory + "\\" + pfilename,true);
//								xtw.WriteElementString("File", pfilename);

								// 以下は通し番号をつけて重複を避けたもの．ただし毎回セーブごとに新しく保存されてしまうので相当無駄である．
//								pfilename = QBasic.Util.getFileNameWithoutPath(be.fileName);
//								int filecount =0;
//								bool flag = true;
//								while(flag)
//								{
//									string newname = filecount.ToString() + "_" + pfilename;
//									if (!System.IO.File.Exists(DefaultDirectory + "\\" + newname))
//									{
//										System.IO.File.Copy(be.fileName,DefaultDirectory + "\\" + newname,true);
//										xtw.WriteElementString("File", newname);
//										flag = false;
//									}
//									filecount++;
//								}

							}
							/*
							else
							{
								xtw.WriteElementString("File", be.fileName);
							}
							*/
                            WriteTag(xtw, be.figureElement);

							break;
						case EVENT.CREATE_INK:// Create_Strokeに置き換わったのでおそらくもう無い．
							Do();
							CreateInkEvent Ie = (CreateInkEvent)ie;
							string file = DefaultDirectory + "\\Ink" + Ie.TimeStamp.ToString() + ".png";
							Bitmap bm = ((BitmapElement)Ie.figureElement).BitMap;
							// save bitmap;
							try
							{
								bm.Save(file,System.Drawing.Imaging.ImageFormat.Png);
							}
							catch(System.Exception e)
							{
								System.Diagnostics.Debug.Fail("Ink bitmap save error on saving slide.",e.ToString());
							}
							// write Xml
							xtw.WriteElementString("Priority",Ie.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", Ie.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", Ie.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", Ie.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", Ie.figureElement.BoundingBox.Height.ToString());
//							if (package) 
							if (true) // 常にインクは自前ディレクトリに保存。
							{
								pfilename = QBasic.Util.getFileNameWithoutPath(file);
								xtw.WriteElementString("File", pfilename);
							}
							/*
							else
							{
								xtw.WriteElementString("File", file);
							}
							*/
                            WriteTag(xtw, Ie.figureElement);
							break;
						case EVENT.CREATE_LINE:
							Do();
							CreateLineEvent le = (CreateLineEvent)ie;
							LineElement l = (LineElement)le.figureElement;
							xtw.WriteElementString("Priority",le.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", le.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", le.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", le.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", le.figureElement.BoundingBox.Height.ToString());
							xtw.WriteElementString("Start_X", l.startX.ToString());	
							xtw.WriteElementString("Start_Y", l.startY.ToString());
							xtw.WriteElementString("End_X", l.endX.ToString());
							xtw.WriteElementString("End_Y", l.endY.ToString());
							xtw.WriteElementString("Color",((LineElement)le.figureElement).FillColor.ToArgb().ToString());
							xtw.WriteElementString("DashStyle",((int)((LineElement)le.figureElement).dashStyle).ToString());
                            WriteTag(xtw, l);
                            break;
						case EVENT.RESIZE_OBJECT:
							Do();
							ResizeObjectEvent roe = (ResizeObjectEvent)ie;
							xtw.WriteElementString("ObjectID", roe.getID().ToString());
							xtw.WriteElementString("X", roe.addX.ToString());
							xtw.WriteElementString("Y", roe.addY.ToString());
							xtw.WriteElementString("W", roe.addW.ToString());
							xtw.WriteElementString("H", roe.addH.ToString());
							break;
						case EVENT.CREATE_EXTERNAL:
							Do();
							CreateExternalEvent xe = (CreateExternalEvent)ie;
							xtw.WriteElementString("Priority",xe.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", xe.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", xe.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", xe.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", xe.figureElement.BoundingBox.Height.ToString());

//							string [] xtmp;
//							if (ExternalElement.IsMacroExternalElement(((ExternalElement)xe.figureElement).filename,out xtmp))
//							{ // マクロの場合、パスは省いて記録
//								pfilename = QBasic.Util.getFileNameWithoutPath(xe.fileName);
//							}
//							else
//							{ // マクロではないとき
//								if (package)
//								{ // 梱包ならば、自前フォルダにコピーして相対パス。
//									pfilename = QBasic.Util.getFileNameWithoutPath(xe.fileName);
//									if (!System.IO.File.Exists(DefaultDirectory + "\\" + pfilename))
//										System.IO.File.Copy(xe.fileName,DefaultDirectory + "\\" + pfilename,true);
//								}
//								else
//								{ // マクロでも梱包でもないので、そのまま保存
//									pfilename = xe.fileName;
//								}
//							}
//							xtw.WriteElementString("File", pfilename);

                            //相対パスになおして保存。
                            string rFile = "";
                            //Uri link = new Uri(xe.fileName);
                            Uri link = new Uri(((ExternalElement)xe.figureElement).filename); // 080328
                            if (linkBaseDir != "")
                            {
                                if (!linkBaseDir.EndsWith("\\")) linkBaseDir += "\\";
                                Uri basePresenPath = new Uri(linkBaseDir);
                                rFile = basePresenPath.MakeRelativeUri(link).ToString();
                            }
                            else
                            {
                                rFile = link.ToString();
                            }
                            //どうやらUrlはToStringするとかってにUrlEncodeされるらしい。
                            string ss = rFile;// System.Web.HttpUtility.UrlEncode(rFile);
                            xtw.WriteElementString("File", ss);

							//xtw.WriteElementString("File", xe.fileName);
							/*							
							if (package)
							{
								string [] xtmp;
								if (!((ExternalElement)xe.figureElement).IsMacroExternalElement(out xtmp))
								{
									pfilename = QBasic.Util.getFileNameWithoutPath(xe.fileName);
									if (!System.IO.File.Exists(DefaultDirectory + "\\" + pfilename))
										System.IO.File.Copy(xe.fileName,DefaultDirectory + "\\" + pfilename,true);
								}
								else
								{
									pfilename = xe.fileName;
								}
								xtw.WriteElementString("File", pfilename);
							}
							else
							{
								xtw.WriteElementString("File", xe.fileName);
							}
*/
                            WriteTag(xtw, xe.figureElement);

							break;
                        case EVENT.CREATE_LINK_IMAGE:
                            Do();
                            CreateLinkImageEvent lie = (CreateLinkImageEvent)ie;
                            xtw.WriteElementString("Priority", lie.figureElement.Priority.ToString());
                            xtw.WriteElementString("Rect_X", lie.figureElement.BoundingBox.X.ToString());
                            xtw.WriteElementString("Rect_Y", lie.figureElement.BoundingBox.Y.ToString());
                            xtw.WriteElementString("Rect_W", lie.figureElement.BoundingBox.Width.ToString());
                            xtw.WriteElementString("Rect_H", lie.figureElement.BoundingBox.Height.ToString());

                            LinkImageElement liee = (LinkImageElement)lie.figureElement;
                            Uri lnk = new Uri(liee.filename);
                            //どうやらUrlはToStringするとかってにUrlEncodeされるらしい。
                            xtw.WriteElementString("File", lnk.ToString());

                            xtw.WriteElementString("Hash",
                                System.Web.HttpUtility.HtmlDecode(liee.Hash));
                            xtw.WriteElementString("RefleshRate", liee.RefleshRate.ToString());
                            xtw.WriteElementString("Persist", liee.Persist.ToString());

                            WriteTag(xtw, lie.figureElement);

                            break;
                        case EVENT.GROUP_START:
							stepForward();
							//Do();
							break;
						case EVENT.GROUP_END:
							stepForward();
							//Do();
							break;
						case EVENT.CREATE_ELEMENT_GROUP:
							Do();
							CreateElementGroupEvent ege = (CreateElementGroupEvent)ie;
							xtw.WriteElementString("Priority",ege.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", ege.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", ege.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", ege.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", ege.figureElement.BoundingBox.Height.ToString());
							ege.getGroupElementIDs(ref indexList);
							xtw.WriteElementString("ElementsNum", indexList.Count.ToString());
							xtw.WriteStartElement("Elements");
							for(int i=0;i<indexList.Count;i++)
							{
								xtw.WriteElementString("ElementID", ((int)indexList[i]).ToString());
							}
							xtw.WriteEndElement(); // Elements
                            WriteTag(xtw, ege.figureElement);
                            break;
/*
						case EVENT.RELEASE_ELEMENT_GROUP:
							EraseObjectEvent ee = (EraseObjectEvent)ie;
							xtw.WriteElementString("ObjectID", ee.getID().ToString());
							Do(); // このイベントは、IDを得るために後からDoする。
							break;
*/
						case EVENT.CREATE_STROKE:
							Do();
							CreateStrokeEvent se = (CreateStrokeEvent)ie;
							xtw.WriteElementString("Priority",se.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", se.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", se.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", se.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", se.figureElement.BoundingBox.Height.ToString());
							xtw.WriteElementString("ID",((StrokeElement)se.figureElement).ID.ToString());
                            WriteTag(xtw, se.figureElement);
                            break;
						case EVENT.CREATE_RECOG_GROUP:
							Do();
							CreateRecogGroupEvent rge = (CreateRecogGroupEvent)ie;
							xtw.WriteElementString("Priority",rge.figureElement.Priority.ToString());
							xtw.WriteElementString("Rect_X", rge.figureElement.BoundingBox.X.ToString());
							xtw.WriteElementString("Rect_Y", rge.figureElement.BoundingBox.Y.ToString());
							xtw.WriteElementString("Rect_W", rge.figureElement.BoundingBox.Width.ToString());
							xtw.WriteElementString("Rect_H", rge.figureElement.BoundingBox.Height.ToString());
							rge.getGroupElementIDs(ref indexList);
							xtw.WriteElementString("PreElementsNum", indexList.Count.ToString());
							xtw.WriteStartElement("PreElements");
							for(int i=0;i<indexList.Count;i++)
							{
								xtw.WriteElementString("ElementID", ((int)indexList[i]).ToString());
							}
							xtw.WriteEndElement(); // Elements
							rge.getRecogGroupElementIDs(ref indexList);
							xtw.WriteElementString("PostElementsNum", indexList.Count.ToString());
							xtw.WriteStartElement("PostElements");
							for(int i=0;i<indexList.Count;i++)
							{
								xtw.WriteElementString("ElementID", ((int)indexList[i]).ToString());
							}
							xtw.WriteEndElement(); // Elements
                            WriteTag(xtw, rge.figureElement);

							break;
						default:
							// unable to reach here
							System.Diagnostics.Debug.Fail("Slide Save error. [unknown structure]");
							break;
					}
					xtw.WriteEndElement();

					if (currentPosition == positionToSave) break;

					//Application.DoEvents();
				}
				xtw.WriteEndElement(); // end of slide
				xtw.WriteEndDocument();
				xtw.Flush();
				xtw.Close();
				elementList.EnableListChanged = true;
				updateDrawList();
                dirty = false;

				return true;
			}
			catch(System.Exception e)
			{
				System.Diagnostics.Debug.Fail("Slide File Save Error.",e.ToString());
				return false;
			}
			finally
			{
				indexList.Clear();
				pbf.Hide();
				pbf.Dispose();
			}
		}
        private void WriteTag(XmlTextWriter xtw, FigureElement fe)
        {
            xtw.WriteElementString("Tag", 
                System.Web.HttpUtility.HtmlEncode(fe.Tag));
        }

		public void SaveAsSimpleXml(string slidefile,bool package)
		{
			ArrayList newEventList = new ArrayList();

			IEvent ev;
			ev = new GroupStartEvent();
			newEventList.Add(ev);
			ev.TimeStamp = DateTime.Now.Ticks;

			IEnumerator enume = elementList.GetEnumerator();
			FigureElement fe,ce;
			CreateObjectEvent coe;
			while (enume.MoveNext())
			{
				fe =(FigureElement)enume.Current;
				//fe.createCopy(out ce);
				//ce.createCreateEvent(elementList,out coe);
				fe.createCreateEvent(elementList,out coe);
				newEventList.Add(coe);
				coe.TimeStamp = DateTime.Now.Ticks;
				//Application.DoEvents();
			}
			ev = new GroupEndEvent();
			newEventList.Add(ev);
			ev.TimeStamp = DateTime.Now.Ticks;
			// save
			//this.clearAll();
			
			//elementList.Clear();
			//drawList.Clear();
			eventList.Clear();
			currentPosition = 0;
			//dirty = false;
			
			eventList = newEventList;
			//dirty = true;
			this.SaveAsXml(slidefile,package);

			//本当ならばeventListを復活させるべき．
			//newEventList.Clear();
		}

	}

}
